package cn.zwx.member.svc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.zwx.base.exception.BizWrapException;
import cn.zwx.base.projo.SortablePageParam;
import cn.zwx.base.projo.SortingField;
import cn.zwx.base.utils.PageUtil;
import cn.zwx.common.mybatis.query.LambdaQueryWrapperX;
import cn.zwx.member.svc.domain.convert.exception.ExceptionWrap;
import cn.zwx.member.svc.domain.convert.group.MemberGroupWrap;
import cn.zwx.member.svc.domain.entity.MemberGroupEntity;
import cn.zwx.member.svc.domain.enums.MemberBizCodeEnum;
import cn.zwx.member.svc.dto.MemberGroupCreateDTO;
import cn.zwx.member.svc.dto.MemberGroupPageDTO;
import cn.zwx.member.svc.dto.MemberGroupUpdateDTO;
import cn.zwx.member.svc.mapper.MemberGroupMapper;
import cn.zwx.member.svc.service.MemberGroupService;
import cn.zwx.member.svc.service.MemberUserService;
import cn.zwx.member.svc.vo.MemberGroupSimpleVO;
import cn.zwx.member.svc.vo.MemberGroupVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author zhangwenxue
 */
@Service
public class MemberGroupServiceImpl implements MemberGroupService {
    @Resource
    private MemberGroupMapper mapper;

    @Resource
    private MemberUserService memberUserService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createGroup(MemberGroupCreateDTO dto) throws BizWrapException {
        // 1.check name
        String name = dto.getName();
        Long selectCount = mapper.selectCount(new LambdaQueryWrapperX<MemberGroupEntity>()
                .eq(MemberGroupEntity::getName, name));
        if (selectCount > 0){
            throw ExceptionWrap.wrap(MemberBizCodeEnum.MEMBER_GROUP_EXISTS);
        }
        // 2.build entity
        MemberGroupEntity groupEntity = new MemberGroupEntity();
        groupEntity.setCreator(dto.getUserId().toString());
        groupEntity.setCreateTime(new Date());
        groupEntity.setName(dto.getName());
        groupEntity.setUpdater(dto.getUserId().toString());
        groupEntity.setUpdateTime(new Date());
        groupEntity.setRemark(dto.getRemark());
        groupEntity.setStatus(dto.getStatus());
        // 3.insert
        mapper.insert(groupEntity);
        // 4.return
        return groupEntity.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateGroup(MemberGroupUpdateDTO dto) throws BizWrapException {
        // 1.查询是否存在
        MemberGroupEntity groupEntity = mapper.selectById(dto.getId());
        if (groupEntity == null){
            return false;
        }
        // 2.判断是否重名
        Long selectCount = mapper.selectCount(new LambdaQueryWrapperX<MemberGroupEntity>()
                .eq(MemberGroupEntity::getName, dto.getName())
                .ne(MemberGroupEntity::getId,dto.getId()));
        if (selectCount > 0){
            throw ExceptionWrap.wrap(MemberBizCodeEnum.MEMBER_GROUP_EXISTS);
        }
        // 3.builder entity
        groupEntity.setUpdater(dto.getUserId().toString());
        groupEntity.setUpdateTime(new Date());
        groupEntity.setName(dto.getName());
        groupEntity.setRemark(dto.getRemark());
        groupEntity.setStatus(dto.getStatus());
        // 4.update
        int updateById = mapper.updateById(groupEntity);
        return updateById == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteGroup(Long id) throws BizWrapException {
        // 校验存在
        validateGroupExists(id);
        // 校验分组下是否有用户
        validateGroupHasUser(id);
        // 删除
        int deleteById = mapper.deleteById(id);
        return deleteById == 1;
    }

    @Override
    public MemberGroupVO getGroup(Long id) {
        // 1.query
        MemberGroupEntity groupEntity = mapper.selectById(id);
        if (null == groupEntity){
            return null;
        }
        // 2.return
        return MemberGroupWrap.convert(groupEntity);
    }

    @Override
    public List<MemberGroupSimpleVO> getSimpleGroupList() {
        // 1.query
        List<MemberGroupEntity> selectList = mapper.selectList(new LambdaQueryWrapperX<MemberGroupEntity>()
                .eq(MemberGroupEntity::getStatus, 0));
        if (CollUtil.isEmpty(selectList)){
            return new ArrayList<>();
        }
        // 2.query group member
        List<MemberGroupSimpleVO> returnList = new ArrayList<>();
        selectList.forEach(t->{
            final MemberGroupSimpleVO memberGroupSimpleVO = new MemberGroupSimpleVO();
            memberGroupSimpleVO.setId(t.getId());
            memberGroupSimpleVO.setName(t.getName());
            returnList.add(memberGroupSimpleVO);
        });
        return returnList;
    }

    @Override
    public PageUtil<MemberGroupVO> getGroupPage(MemberGroupPageDTO pageVO) {
        // 1.query
        SortablePageParam param = new SortablePageParam();
        param.setPageNo(pageVO.getPageNo());
        param.setPageSize(pageVO.getPageSize());
        List<SortingField> sortingFields = new ArrayList<>();
        sortingFields.add(new SortingField("create_time", SortingField.ORDER_DESC));
        param.setSortingFields(sortingFields);
        LambdaQueryWrapperX<MemberGroupEntity> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(MemberGroupEntity::getDeleted, 0);
        queryWrapperX.likeIfPresent(MemberGroupEntity::getName, pageVO.getName());
        queryWrapperX.betweenIfPresent(MemberGroupEntity::getCreateTime, pageVO.getStartTime(), pageVO.getEndTime());
        queryWrapperX.eqIfPresent(MemberGroupEntity::getStatus, pageVO.getStatus());
        PageUtil<MemberGroupEntity> selectPage = mapper.selectPage(param, queryWrapperX);
        List<MemberGroupEntity> records = selectPage.getRecords();
        // 2.return
        PageUtil<MemberGroupVO> returnPage = new PageUtil<>(selectPage.getPage(),
                selectPage.getCurrent(),selectPage.getTotal(),new ArrayList<>());
        if (CollUtil.isEmpty(records)){
            return returnPage;
        }
        List<MemberGroupVO> returnList = new ArrayList<>();
        records.forEach(t->{
            MemberGroupVO memberGroupVO = new MemberGroupVO();
            BeanUtils.copyProperties(t, memberGroupVO);
            Instant instant = t.getCreateTime().toInstant();
            LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
            memberGroupVO.setCreateTime(localDateTime);
            returnList.add(memberGroupVO);
        });
        return  new PageUtil<>(selectPage.getPage(),
                selectPage.getCurrent(),selectPage.getTotal(),returnList);
    }


    private void validateGroupHasUser(Long id) throws BizWrapException {
        Long count = memberUserService.getUserCountByGroupId(id);
        if (count > 0) {
            throw ExceptionWrap.wrap(MemberBizCodeEnum.GROUP_HAS_USER);
        }
    }

    private void validateGroupExists(Long id) throws BizWrapException {
        MemberGroupEntity groupEntity = mapper.selectById(id);
        if (groupEntity == null){
            throw  ExceptionWrap.wrap(MemberBizCodeEnum.MEMBER_GROUP_NOT_EXISTS);
        }
    }
}
